var $;
var urlBase = 'http://amoebathegame.googlecode.com/svn/trunk/';

function init() {
  if (wave != null && wave.isInWaveContainer()) {
    google.load("jquery", "1.3.2");
    google.setOnLoadCallback(function () {
      Game.init($('#content'));
      wave.setStateCallback(Game.stateCallback, Game);
      wave.setParticipantCallback(Game.participantCallback, Game);
    });
  }
  /* Fake wave calls to indicate initial State callback */
  /*
  wave._addParticipant('test1', 'test1Name', '');
  wave._addParticipant('test2', 'test2Namesjkdthadjkghadjksghalkdjsgh', '');
  
  wave.State.submitDelta({});
  */
}

var Game = {
  $div: null,
  size: 10,
  markSize: 20,
  fields: [],
  marks:[],
  playerX: 'none',
  playerO: 'none',
  isUpdating: false,
  status: '',
  marksSrc: ['', 'url('+urlBase+'img/x20.png)', 'url('+urlBase+'img/o20.png)'],
  side: 0,
  directions: null,
  init: function($c) {
    this.directions = [1, this.size, this.size + 1];
    this.$div = $c
    this.$div.css({ position: 'relative', width: 200, height: 250 });
    this.$field = $('<div class="field"/>');
    this.$div.append(this.$field);
    for (var x = 0; x < this.size; x++) {
      for (var y = 0; y < this.size; y++) {
        var $f = $('<div class="fieldItem"/>').css({ 
          'position': 'absolute',
          'top': y*this.markSize,
          'left': x*this.markSize,
          'width': this.markSize,
          'height': this.markSize
        }).attr({
          posx: x,
          posy: y
        }).click(function(){
          var x1 = x, y1 = y;
          return function(){
            return Game.fieldClicked(x1, y1);
          }
        }());
        this.$field.append($f);
        this.fields.push($f);
        this.marks.push(0);
      }
    }
    this.$x = $('<div class="player"><img/></div>').css({ 
      top: 210,
      left: 0
    }).click(function(){
      return Game.sitToggle('X');
    });
    this.$imgX = $('img', this.$x).attr('src', urlBase + 'img/sithere.png');
    this.$o = $('<div class="player"><img/></div>').css({ 
      top: 210,
      left: 160
    }).click(function(){
      return Game.sitToggle('O');
    });
    this.$imgO = $('img', this.$o).attr('src', urlBase + 'img/sithere.png');
    this.$win = $('<div class="win"/>').hide();
    this.$field.append(this.$x).append(this.$o).append(this.$win);
  },
  fieldClicked: function(x, y){
    var i = this.size * x + y;
    var state = wave.getState();
    var next = state.get('next', 'n');
    var me = wave.getViewer().getId();
    /*alert('click:'+[x, y, this.side, this.marks[i]].join(', '));*/
    if (this.side && this.marks[i] == 0 && this.status == 'ingame' && next == me) {
      this.marks[i] = this.side;
      this.updateState(wave.getState(), {
        'marks': wave.util.printJson(this.marks),
        'next': me/*this.getOpponent()*/
      });
    }
    return 0;
  },
  sitToggle: function(player) {
    if (this.isUpdating) { return 0; }
    var state = wave.getState();
    var p = {};
    p.X = state.get('playerX', 'none');
    p.O = state.get('playerO', 'none');
    var me = wave.getViewer().getId();
    /* If noone is sitting there */
    if (p[player] == 'none') {
      /* Sit in */
      if (p.X == me || p.O == me) {
        /* You are already sitting */
        return 0;
      }
      this.updateState(state, 'player'+player, me);
      this.isUpdating = true;
    } else if (p[player] == me) {
      /* Sit out */
      this.updateState(state, 'player'+player, 'none');
    }
    return 0;
  },
  updateState: function(state, a, b) {
    if (typeof(a) == 'object') {
      state.submitDelta(a);
    } else {
      state.submitValue(a, b);
    }
    this.isUpdating = true;
  },
  stateCallback : function() {
    var state = wave.getState();
    var me = wave.getViewer().getId();
    var pX = state.get('playerX', 'none');
    var pO = state.get('playerO', 'none');
    if (this.playerX != pX) {
      if (pX != 'none') {
        /* playerX sat */
        this.$imgX.attr('src', wave.getParticipantById(pX).getThumbnailUrl());
      } else {
        this.$imgX.attr('src', urlBase + 'img/sithere.png');
      }
      this.playerX = pX;
    }
    if (this.playerO != pO) {
      if (pO != 'none') {
        /* playerO sat */
        this.$imgO.attr('src', wave.getParticipantById(pO).getThumbnailUrl());
      } else {
        this.$imgO.attr('src', urlBase + 'img/sithere.png');
      }
      this.playerO = pO;
    }
    if (pX == me) {
      this.side = 1;
    } else if (pO == me) {
      this.side = 2;
    } else {
      this.side = 0;
    }
    var m;
    eval('m = ' + state.get('marks', 'null'));
    if (m != null) {
      this.marks = m;
    }
    for (var i = 0; i < this.marks.length; i++) {
      this.fields[i].css('background-image', this.marksSrc[this.marks[i]]);
    }
    var next = state.get('next', 'n');
    if (pX == next) {
      this.$x.css('border', '2px solid red');
    } else {
      this.$x.css('border', 'none');
    }
    if (pO == next) {
      this.$o.css('border', '2px solid red');
    } else {
      this.$o.css('border', 'none');
    }
    
    /*
     * states:
     *   sitting - ingame 
     */
    if (pX != 'none' && pO != 'none') {
      /* ready for the game; pX starts */
      if (this.status == 'sitting' && this.side == 1) {
        /* both just sat in; X can clear the field */
        this.clear();
      }
      this.status = 'ingame';
      var win;
      eval('win = ' + state.get('win', 'null'));
      if (win == null && next == me) {
        /* next player checks for game end */
        var win = this.checkWin();
        if (win != null) {
          this.won(win);
        }
      }
      if (win != null) {
        this.status = 'gameover';
        this.drawWon(win);
        /* TODO: show new game popup */
      } else {
        this.$win.hide();
      }
    } else {
      this.status = 'sitting';
    }
    this.isUpdating = false;
  },
  checkWin: function() {
    if (1) return null;
    var m = this.marks;
    var check5 = function(i, dir) {
      var n = i + dir;
      if (n < m.length && m[i] == m[n]) {
        return 1 + check5(n, dir);
      } else {
        return 0;
      }
    };
    
    for (var x = 0; x < this.size - 5; x++) {
      for (var y = 0; y < this.size - 5; y++) {
        var n = x * this.size + y;
        if (this.marks[n] == null) continue;
        for (var i = 0; i < 3; i++) {
          /* 3 directions (down, right, down-right) */
          var cnt = check5(n, this.directions[i]);
          if (cnt >= 5) {
            return [x, y, i, cnt];
          }
        }
      }
    }
    return null;
  },
  won: function(win) {
    this.updateState(wave.getState(), {
      'next': 'n',
      'win': wave.util.printJson(win)
    });
  },
  drawWon: function(win) {
    /* win = [x, y, i, cnt] */
    var dirs = [[0,1], [1,0], [1,1]];
    this.$win.empty().show();
    for (var i = 0; i < win[3]; i++) {
      $('<div><img src="'+urlBase+'img/win.png"/></div>').css({
        'left': (win[0] + dirs[win[2]][0] * i) * this.markSize,
        'top': (win[1] + dirs[win[2]][1] * i) * this.markSize,
        'width': this.markSize,
        'height': this.markSize,
        'opacity': 0.3
      }).appendTo(this.$win);
    }
  },
  clear: function() {
    for (var i=0; i < 100; i++) {
      this.marks[i] = 0;
    }
    this.updateState(wave.getState(), {
      'marks': wave.util.printJson(this.marks),
      'next': wave.getViewer().getId(),
      'win': 'null'
    });
  },
  getOpponent: function() {
    var state = wave.getState();
    var opp = 'none';
    if (this.side == 1) {
      opp = state.get('playerO', opp);
    } else if (this.side == 2) {
      opp = state.get('playerX', opp);
    }
    return opp;
  },
  participantCallback : function() {
    var participants = wave.getParticipants();
    if (participants.length == 0) return;
    /*
    for (var i in participants) {
      var html = '<div class="participant">'
        + '<div class="background"></div>'
        + '<div class="foreground"><span class="participantId">'
        + participants[i].getId() + '</span><br/>'
        + '<span class="participantName">'
        + participants[i].getDisplayName() + '</span></div></div>';
      var $html = $(html);
      this.$div.append($html);
      $html.attr('participant_id', participants[i].getId())
        .click(function() {
          Game.participantClicked($(this).attr('participant_id'));
        });
    }
    */
  }
};

gadgets.util.registerOnLoadHandler(init);

/*
$(document).ready(function() {
  Game._div = $('#content');
  init();
});
*/